import json
import re
from audioop import reverse
from random import randint
from home.models import ArticleCategory, Article
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseBadRequest, HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.views import View
from django_redis import get_redis_connection

from beifangokk.urls import logger
from home.models import ArticleCategory
from libs.captcha import captcha
from libs.yuntongxun.sms import CCP
from users.models import User
from utils.response_code import RETCODE


class RegisterView(View):
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        sms_code = request.POST.get('sms_code')
        if not all([mobile, password, password2, sms_code]):
            return HttpResponse('参数不全')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('手机号码格式不正确')
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password) or not re.match(r'^[0-9a-zA-Z]{8,20}$', password2):
            return HttpResponseBadRequest('密码长度,格式不正确，长度8-20,必须是数字,字母')
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一样')
        redis_conn = get_redis_connection('default')
        sms_code_redis = redis_conn.get('sms:%s' % mobile)
        if sms_code_redis is None:
            return HttpResponseBadRequest('短信验证码过期')
        user = User.objects.create_user(username=mobile, mobile=mobile, password=password)
        login(request, user)
        resp = redirect(reverse('home:index'))
        resp.set_cookie('is_login', True)
        resp.set_cookie('login_name', user.username)
        return resp

    # 验证码视图


class ImageView(View):
    def get(self, request):
        uuid = request.GET.get('uuid')
        if uuid is None:
            return HttpResponseBadRequest('没有获取到uuid')
        txt, image = captcha.generate_captcha()
        redis_conn = get_redis_connection('default')
        redis_conn.setex(name='img:%s' % uuid, time=300, value=txt)
        return HttpResponse(image, content_type='image/jpeg')


class SmsCodeView(LoginRequiredMixin, View):

    def get(self, request):
        """
        1.接收参数
        2.参数的验证
            2.1 验证参数是否齐全
            2.2 图片验证码的验证
                连接redis，获取redis中的图片验证码
                判断图片验证码是否存在
                如果图片验证码未过期，我们获取到之后就可以删除图片验证码
                比对图片验证码
        3.生成短信验证码
        4.保存短信验证码到redis中
        5.发送短信
        6.返回响应
        :param request:
        :return:
        """
        # 1.接收参数 （查询字符串的形式传递过来）
        mobile = request.GET.get('mobile')
        image_code = request.GET.get('image_code')
        uuid = request.GET.get('uuid')
        # 2.参数的验证
        #     2.1 验证参数是否齐全
        if not all([mobile, image_code, uuid]):
            return JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必要的参数'})
        #     2.2 图片验证码的验证
        #         连接redis，获取redis中的图片验证码
        redis_conn = get_redis_connection('default')
        redis_image_code = redis_conn.get('img:%s' % uuid)
        #         判断图片验证码是否存在
        if redis_image_code is None:
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图片验证码已过期'})
        #         如果图片验证码未过期，我们获取到之后就可以删除图片验证码
        try:
            redis_conn.delete('img:%s' % uuid)
        except Exception as e:
            logger.error(e)
        #         比对图片验证码, 注意大小写的问题， redis的数据是bytes类型
        if redis_image_code.decode().lower() != image_code.lower():
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图片验证码错误'})
        # 3.生成短信验证码
        sms_code = '%06d' % randint(0, 999999)
        # 为了后期比对方便，我们可以将短信验证码记录到日志中
        logger.info(sms_code)
        # 4.保存短信验证码到redis中
        redis_conn.setex('sms:%s' % mobile, 300, sms_code)
        # 5.发送短信
        # 参数1： 测试手机号
        # 参数2：模板内容列表： {1} 短信验证码   {2} 分钟有效
        # 参数3：模板 免费开发测试使用的模板ID为1
        CCP().send_template_sms(mobile, [sms_code, 5], 1)
        # 6.返回响应
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '短信发送成功'})


class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        username = request.POST.get('mobile')
        password = request.POST.get('password')
        remember = request.POST.get('remember')
        if not all([username, password]):
            return render(request, template_name='login.html', context={'msg': '账号或密码不能为空'})
        if not re.match(r'^1[3-9]\d{9}$', username):
            return render(request, template_name='login.html', context={'msg': '手机号码格式不正确'})
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password):
            return render(request, template_name='login.html', context={'msg': '密码格式不正确'})
        return_user = authenticate(mobile=username, password=password)
        if return_user is None:
            return render(request, template_name='login.html', context={'msg': '账号或密码错误'})
        login(request, return_user)
        next_page = request.GET.get('next')
        if next_page:
            resp = redirect(next_page)
        else:
            resp = redirect('/')
        # resp = redirect(reverse('home:index'))

        if remember != 'on':
            resp.set_cookie('is_login', True)
            username = json.dumps(return_user.username)
            resp.set_cookie('login_name', username)
            request.session.set_expiry(0)
        else:
            resp.set_cookie('is_login', True, max_age=24 * 3600 * 14)
            username = json.dumps(return_user.username)
            resp.set_cookie('login_name', username, max_age=24 * 3600 * 14)
            request.session.set_expiry(None)
        return resp


class LogoutView(View):
    def get(self, request):
        logout(request)
        resp = redirect('/')
        resp.delete_cookie('is_login')
        resp.delete_cookie('login_name')
        return resp


class ForgetPasswordView(View):
    def get(self, request):
        return render(request, 'forget_password.html')

    def post(self, request):
        # 接收参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        smscode = request.POST.get('sms_code')

        # 判断参数是否齐全
        if not all([mobile, password, password2, smscode]):
            return HttpResponseBadRequest('缺少必传参数')

        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('请输入正确的手机号码')

        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseBadRequest('请输入8-20位的密码')

        # 判断两次密码是否一致
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一致')

        # 验证短信验证码
        redis_conn = get_redis_connection('default')
        sms_code_server = redis_conn.get('sms:%s' % mobile)
        if sms_code_server is None:
            return HttpResponseBadRequest('短信验证码已过期')
        if smscode != sms_code_server.decode():
            return HttpResponseBadRequest('短信验证码错误')

        # 根据手机号查询数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果该手机号不存在，则注册个新用户
            try:
                User.objects.create_user(username=mobile, mobile=mobile, password=password)
            except Exception:
                return HttpResponseBadRequest('修改失败，请稍后再试')
        else:
            # 修改用户密码
            user.set_password(password)
            user.save()

        # 跳转到登录页面
        response = redirect('/login')

        return response


class UserCenterView(LoginRequiredMixin, View):
    def get(self, request):
        userinfo = request.user
        content = {
            'username': userinfo.username,
            'mobile': userinfo.mobile,
            'avatar': userinfo.avatar.url if userinfo.avatar else None,
            'user_desc': userinfo.user_desc
        }
        return render(request, 'usercenter.html', context=content)

    def post(self, request):
        userinfo = request.user
        username = request.POST.get('username')
        avatar = request.FILES.get('avatar')
        user_desc = request.POST.get('desc')
        try:
            userinfo.username = username
            userinfo.user_desc = user_desc
            if avatar:
                userinfo.avatar = avatar
                userinfo.save()
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('修改用户信息失败')
        resp = redirect('home:index')
        username = json.dumps(username)
        resp.set_cookie('login_name', username)
        return resp


class WriteBlogView(LoginRequiredMixin, View):
    def get(self, request):
        categories = ArticleCategory.objects.all()
        context = {'categories': categories}
        return render(request, 'writeblog.html', context=context)

    def post(self, request):
        avatar = request.FILES.get('avatar')
        title = request.POST.get('title')
        category_id = request.POST.get('category')
        tags = request.POST.get('tags')
        sumary = request.POST.get('sumary')
        content = request.POST.get('content')
        user = request.user
        if not all([avatar, title, category_id, sumary, content]):
            return HttpResponseBadRequest('参数不齐全')
        try:
            category = ArticleCategory.objects.filter(pk=category_id).first()
        except ArticleCategory.DoesNotExist:
            return HttpResponseBadRequest('没有该分类信息')
        try:
            Article.objects.create(
                author=user,
                avatar=avatar,
                category=category,
                tags=tags,
                sumary=sumary,
                content=content,
                title=title,
            )
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('发布失败，请稍后重试')
        return redirect('/')
